package br.senai.sc.web.pontosColeta.beans;

import java.awt.Color;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;

import br.senai.sc.controller.Parametro;
import br.senai.sc.controller.Parametro.Descricao;
import br.senai.sc.controller.Qualidade;
import br.senai.sc.controller.crud.RelatorioAmostra;
import br.senai.sc.controller.exception.BusinessException;
import br.senai.sc.model.Amostra;
import br.senai.sc.model.PontoColeta;
import br.senai.sc.web.charts.QualidadeBarRenderer;

@Named
@SessionScoped
public class GraficoAmostraPorDataBean implements Serializable {

	private static final long serialVersionUID = 1L;

	private StreamedContent grafico;
	private StreamedContent graficoColiformesFecais;
	private StreamedContent graficoDBO;
	private StreamedContent graficoNT;
	private StreamedContent graficoOD;
	private StreamedContent graficoPH;
	private StreamedContent graficoPT;
	private StreamedContent graficoST;
	private StreamedContent graficoTemperatura;
	private StreamedContent graficoTurbidez;

	private List<Amostra> amostras;

	@Inject
	private RelatorioAmostra relatorioAmostra;

	/**
	 * Largura para gerar a imagem do gráfico
	 */
	private static final int GRAFICO_WIDTH = 600;

	/**
	 * Altura para gerar a imagem do gráfico
	 */
	private static final int GRAFICO_HEIGHT = 400;

	/**
	 * Carrega a lista de {@link Amostra} do bean.
	 */
	public void carregarAmostras(PontoColeta pontoColeta, Date dtInicial,
			Date dtFinal) {

		amostras = relatorioAmostra.amostras(pontoColeta, dtInicial, dtFinal);
	}

	public List<Amostra> getAmostras() {
		return amostras;
	}

	public void setAmostras(List<Amostra> amostras) {
		this.amostras = amostras;
	}

	public StreamedContent getGrafico() {
		return grafico;
	}

	public void setGrafico(StreamedContent grafico) {
		this.grafico = grafico;
	}

	public StreamedContent getGraficoDBO() {
		return graficoDBO;
	}

	public void setGraficoDBO(StreamedContent graficoDBO) {
		this.graficoDBO = graficoDBO;
	}

	public StreamedContent getGraficoColiformesFecais() {
		return graficoColiformesFecais;
	}

	public void setGraficoColiformesFecais(
			StreamedContent graficoColiformesFecais) {
		this.graficoColiformesFecais = graficoColiformesFecais;
	}

	public StreamedContent getGraficoNT() {
		return graficoNT;
	}

	public void setGraficoNT(StreamedContent graficoNT) {
		this.graficoNT = graficoNT;
	}

	public StreamedContent getGraficoOD() {
		return graficoOD;
	}

	public void setGraficoOD(StreamedContent graficoOD) {
		this.graficoOD = graficoOD;
	}

	public StreamedContent getGraficoPH() {
		return graficoPH;
	}

	public void setGraficoPH(StreamedContent graficoPH) {
		this.graficoPH = graficoPH;
	}

	public StreamedContent getGraficoPT() {
		return graficoPT;
	}

	public void setGraficoPT(StreamedContent graficoPT) {
		this.graficoPT = graficoPT;
	}

	public StreamedContent getGraficoST() {
		return graficoST;
	}

	public void setGraficoST(StreamedContent graficoST) {
		this.graficoST = graficoST;
	}

	public StreamedContent getGraficoTemperatura() {
		return graficoTemperatura;
	}

	public void setGraficoTemperatura(StreamedContent graficoTemperatura) {
		this.graficoTemperatura = graficoTemperatura;
	}

	public StreamedContent getGraficoTurbidez() {
		return graficoTurbidez;
	}

	public void setGraficoTurbidez(StreamedContent graficoTurbidez) {
		this.graficoTurbidez = graficoTurbidez;
	}

	/**
	 * Cria gráfico para o IQA das {@link Amostra}
	 */
	public void criarGraficoIQA() {
		try {
			JFreeChart chart = ChartFactory.createBarChart3D("IQA por data",
					"Data", "IQA", criarDatasetIQA(), PlotOrientation.VERTICAL,
					false, true, false);
			chart.setBackgroundPaint(Color.WHITE);

			int i = 0;
			Qualidade qualidades[] = new Qualidade[amostras.size()];
			for (Amostra amostra : amostras) {
				qualidades[i] = Qualidade.getQualidade(amostra.getIQA());
				i++;
			}

			QualidadeBarRenderer renderer = new QualidadeBarRenderer(qualidades);

			CategoryPlot categoryPlot = chart.getCategoryPlot();
			categoryPlot.getRangeAxis().setRange(0, 100);
			categoryPlot.setRenderer(renderer);
			categoryPlot.getDomainAxis().setCategoryLabelPositions(
					CategoryLabelPositions
							.createUpRotationLabelPositions(Math.PI / 4));

			File chartFile = new File("grafico");
			ChartUtilities.saveChartAsPNG(chartFile, chart, GRAFICO_WIDTH,
					GRAFICO_HEIGHT);

			grafico = new DefaultStreamedContent(
					new FileInputStream(chartFile), "image/png");

		} catch (IOException e) {
		}
	}

	private CategoryDataset criarDatasetIQA() {
		DefaultCategoryDataset dataset = new DefaultCategoryDataset();

		SimpleDateFormat formatadorData = new SimpleDateFormat("dd/MM/yyyy");
		for (Amostra amostra : amostras) {
			dataset.setValue(amostra.getIQA(), amostra.getData(),
					formatadorData.format(amostra.getData()));
		}

		return dataset;
	}

	/**
	 * Cria gráfico para o IQA do {@link Parametro} da amostra das
	 * {@link Amostra}.
	 */
	private DefaultStreamedContent criarGraficoParametro(
			Descricao descricaoParametro) {
		try {

			String descricao = descricaoParametro.getValor();

			JFreeChart chart = ChartFactory.createBarChart3D(descricao
					+ " por data", "Data", descricao,
					criarDatasetIQAParametro(descricaoParametro),
					PlotOrientation.VERTICAL, false, true, false);
			chart.setBackgroundPaint(Color.WHITE);

			int i = 0;
			Qualidade qualidades[] = new Qualidade[amostras.size()];
			for (Amostra amostra : amostras) {
				qualidades[i] = Qualidade.getQualidade(amostra.getIQA());
				i++;
			}

			QualidadeBarRenderer renderer = new QualidadeBarRenderer(qualidades);

			CategoryPlot categoryPlot = chart.getCategoryPlot();
			categoryPlot.getRangeAxis().setRange(0, 100);
			categoryPlot.setRenderer(renderer);
			categoryPlot.getDomainAxis().setCategoryLabelPositions(
					CategoryLabelPositions
							.createUpRotationLabelPositions(Math.PI / 4));

			File chartFile = new File("grafico" + descricao);
			ChartUtilities.saveChartAsPNG(chartFile, chart, GRAFICO_WIDTH,
					GRAFICO_HEIGHT);

			return new DefaultStreamedContent(new FileInputStream(chartFile),
					"image/png");

		} catch (IOException e) {
			return null;
		}
	}

	private CategoryDataset criarDatasetIQAParametro(
			Descricao descricaoParametro) {
		DefaultCategoryDataset dataset = new DefaultCategoryDataset();

		SimpleDateFormat formatadorData = new SimpleDateFormat("dd/MM/yyyy");
		for (Amostra amostra : amostras) {

			try {
				Parametro parametro = amostra.getParametro(descricaoParametro);
				dataset.setValue(parametro.getIqa(), amostra.getData(),
						formatadorData.format(amostra.getData()));
			} catch (BusinessException e) {
				// TODO Auto-generated catch block
			}
		}

		return dataset;
	}

	public void criarGraficoColiformesFecais() {

		graficoColiformesFecais = criarGraficoParametro(Descricao.COLIFORMES_FECAIS);
	}

	public void criarGraficoDBO() {

		graficoDBO = criarGraficoParametro(Descricao.DBO);
	}

	public void criarGraficoNT() {

		graficoNT = criarGraficoParametro(Descricao.NT);
	}

	public void criarGraficoOD() {

		graficoOD = criarGraficoParametro(Descricao.OD);
	}

	public void criarGraficoPH() {

		graficoPH = criarGraficoParametro(Descricao.PH);
	}

	public void criarGraficoPT() {

		graficoPT = criarGraficoParametro(Descricao.PT);
	}

	public void criarGraficoST() {

		graficoST = criarGraficoParametro(Descricao.ST);
	}

	public void criarGraficoTemperatura() {

		graficoTemperatura = criarGraficoParametro(Descricao.TEMPERATURA);
	}

	public void criarGraficoTurbidez() {

		graficoTurbidez = criarGraficoParametro(Descricao.TURBIDEZ);
	}

}
